/***********************************************************************************************************************
*  OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
*  See also https://openstudio.net/license
***********************************************************************************************************************/

#include "CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.hpp"
#include "CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl.hpp"

#include "Curve.hpp"
#include "Curve_Impl.hpp"
#include "CurveQuadratic.hpp"
#include "CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData.hpp"
#include "CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData_Impl.hpp"
#include "ZoneHVACComponent.hpp"
#include "HVACComponent.hpp"
#include "ModelObjectList.hpp"
#include "ModelObjectList_Impl.hpp"
#include "ZoneHVACWaterToAirHeatPump.hpp"
#include "ZoneHVACWaterToAirHeatPump_Impl.hpp"
#include "AirLoopHVACUnitarySystem.hpp"
#include "AirLoopHVACUnitarySystem_Impl.hpp"
#include "AirflowNetworkEquivalentDuct.hpp"
#include "AirflowNetworkEquivalentDuct_Impl.hpp"
#include "Model.hpp"
#include "Model_Impl.hpp"
#include "Node.hpp"
#include "Node_Impl.hpp"
#include "Schedule.hpp"
#include "Schedule_Impl.hpp"
#include "ScheduleTypeRegistry.hpp"

#include <utilities/idd/OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFit_FieldEnums.hxx>

#include <utilities/idd/IddEnums.hxx>
#include "../utilities/core/Assert.hpp"
#include "../utilities/data/DataEnums.hpp"
#include "../utilities/idf/WorkspaceExtensibleGroup.hpp"

namespace openstudio {
namespace model {

  namespace detail {

    CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl(const IdfObject& idfObject,
                                                                                                                           Model_Impl* model,
                                                                                                                           bool keepHandle)
      : WaterToAirComponent_Impl(idfObject, model, keepHandle) {
      OS_ASSERT(idfObject.iddObject().type() == CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType());
    }

    CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl(
      const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle)
      : WaterToAirComponent_Impl(other, model, keepHandle) {
      OS_ASSERT(other.iddObject().type() == CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType());
    }

    CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl(
      const CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl& other, Model_Impl* model, bool keepHandle)
      : WaterToAirComponent_Impl(other, model, keepHandle) {}

    const std::vector<std::string>& CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::outputVariableNames() const {
      static const std::vector<std::string> result{"Cooling Coil Electricity Rate",
                                                   "Cooling Coil Total Cooling Rate",
                                                   "Cooling Coil Sensible Cooling Rate",
                                                   "Cooling Coil Source Side Heat Transfer Rate",
                                                   "Cooling Coil Part Load Ratio",
                                                   "Cooling Coil Runtime Fraction",
                                                   "Cooling Coil Air Mass Flow Rate",
                                                   "Cooling Coil Air Inlet Temperature",
                                                   "Cooling Coil Air Inlet Humidity Ratio",
                                                   "Cooling Coil Air Outlet Temperature",
                                                   "Cooling Coil Air Outlet Humidity Ratio",
                                                   "Cooling Coil Source Side Mass Flow Rate",
                                                   "Cooling Coil Source Side Inlet Temperature",
                                                   "Cooling Coil Source Side Outlet Temperature",
                                                   "Cooling Coil Upper Speed Level",
                                                   "Cooling Coil Neighboring Speed Levels Ratio",
                                                   "Cooling Coil Recoverable Heat Transfer Rate",
                                                   "Cooling Coil Electricity Energy",
                                                   "Cooling Coil Total Cooling Energy",
                                                   "Cooling Coil Sensible Cooling Energy",
                                                   "Cooling Coil Latent Cooling Energy",
                                                   "Cooling Coil Latent Cooling Rate",
                                                   "Cooling Coil Source Side Heat Transfer Energy"};
      return result;
    }

    IddObjectType CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::iddObjectType() const {
      return CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType();
    }

    std::vector<ScheduleTypeKey> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::getScheduleTypeKeys(const Schedule& schedule) const {
      std::vector<ScheduleTypeKey> result;
      UnsignedVector fieldIndices = getSourceIndices(schedule.handle());
      UnsignedVector::const_iterator b(fieldIndices.begin());
      UnsignedVector::const_iterator e(fieldIndices.end());
      if (std::find(b, e, OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::AvailabilityScheduleName) != e) {
        result.push_back(ScheduleTypeKey("CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit", "Availability Schedule"));
      }
      return result;
    }

    unsigned CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::airInletPort() const {
      return OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::IndoorAirInletNodeName;
    }

    unsigned CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::airOutletPort() const {
      return OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::IndoorAirOutletNodeName;
    }

    unsigned CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::waterInletPort() const {
      return OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::WatertoRefrigerantHXWaterInletNodeName;
    }

    unsigned CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::waterOutletPort() const {
      return OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::WatertoRefrigerantHXWaterOutletNodeName;
    }

    boost::optional<Schedule> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::optionalAvailabilitySchedule() const {
      return getObject<ModelObject>().getModelObjectTarget<Schedule>(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::AvailabilityScheduleName);
    }

    Schedule CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::availabilitySchedule() const {
      boost::optional<Schedule> value = optionalAvailabilitySchedule();
      if (!value) {
        // it is an error if we get here, however we don't want to crash
        // so we hook up to global always on schedule
        LOG(Error, "Required availability schedule not set, using 'Always On' schedule");
        value = this->model().alwaysOnDiscreteSchedule();
        OS_ASSERT(value);
        const_cast<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl*>(this)->setAvailabilitySchedule(*value);
        value = optionalAvailabilitySchedule();
      }
      OS_ASSERT(value);
      return value.get();
    }

    int CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::nominalSpeedLevel() const {
      boost::optional<int> value = getInt(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::NominalSpeedLevel, true);
      OS_ASSERT(value);
      return value.get();
    }

    boost::optional<double>
      CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() const {
      return getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::GrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel,
                       true);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::isGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevelAutosized() const {
      bool result = false;
      boost::optional<std::string> value =
        getString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::GrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel, true);
      if (value) {
        result = openstudio::istringEqual(value.get(), "autosize");
      }
      return result;
    }

    boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::ratedAirFlowRateAtSelectedNominalSpeedLevel() const {
      return getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedAirFlowRateAtSelectedNominalSpeedLevel, true);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::isRatedAirFlowRateAtSelectedNominalSpeedLevelAutosized() const {
      bool result = false;
      boost::optional<std::string> value =
        getString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedAirFlowRateAtSelectedNominalSpeedLevel, true);
      if (value) {
        result = openstudio::istringEqual(value.get(), "autosize");
      }
      return result;
    }

    boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::ratedWaterFlowRateAtSelectedNominalSpeedLevel() const {
      return getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedWaterFlowRateAtSelectedNominalSpeedLevel, true);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::isRatedWaterFlowRateAtSelectedNominalSpeedLevelAutosized() const {
      bool result = false;
      boost::optional<std::string> value =
        getString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedWaterFlowRateAtSelectedNominalSpeedLevel, true);
      if (value) {
        result = openstudio::istringEqual(value.get(), "autosize");
      }
      return result;
    }

    double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::nominalTimeforCondensatetoBeginLeavingtheCoil() const {
      boost::optional<double> value =
        getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::NominalTimeforCondensatetoBeginLeavingtheCoil, true);
      OS_ASSERT(value);
      return value.get();
    }

    double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity() const {
      boost::optional<double> value = getDouble(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::InitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity, true);
      OS_ASSERT(value);
      return value.get();
    }

    double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::maximumCyclingRate() const {
      boost::optional<double> value = getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::MaximumCyclingRate, true);
      OS_ASSERT(value);
      return value.get();
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setAvailabilitySchedule(Schedule& schedule) {
      bool result = setSchedule(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::AvailabilityScheduleName,
                                "CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit", "Availability Schedule", schedule);
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setMaximumCyclingRate(double maximumCyclingRate) {
      const bool result = setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::MaximumCyclingRate, maximumCyclingRate);
      // OS_ASSERT(result);
      return result;
    }

    double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::latentCapacityTimeConstant() const {
      boost::optional<double> value = getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::LatentCapacityTimeConstant, true);
      OS_ASSERT(value);
      return value.get();
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setLatentCapacityTimeConstant(double latentCapacityTimeConstant) {
      const bool result =
        setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::LatentCapacityTimeConstant, latentCapacityTimeConstant);
      // OS_ASSERT(result);
      return result;
    }

    double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::fanDelayTime() const {
      boost::optional<double> value = getDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::FanDelayTime, true);
      OS_ASSERT(value);
      return value.get();
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setFanDelayTime(double fanDelayTime) {
      const bool result = setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::FanDelayTime, fanDelayTime);
      // OS_ASSERT(result);
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::useHotGasReheat() const {
      boost::optional<std::string> value = getString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::UseHotGasReheat, true);
      OS_ASSERT(value);
      return openstudio::istringEqual(value.get(), "Yes");
    }

    Curve CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::energyPartLoadFractionCurve() const {
      boost::optional<Curve> value = optionalEnergyPartLoadFractionCurve();
      if (!value) {
        LOG_AND_THROW(briefDescription() << " does not have an Energy Part Load Fraction Curve attached.");
      }
      return value.get();
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setNominalSpeedLevel(int nominalSpeedLevel) {
      bool result = setInt(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::NominalSpeedLevel, nominalSpeedLevel);
      OS_ASSERT(result);
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(
      boost::optional<double> grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel) {
      bool result(false);
      if (grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel) {
        result =
          setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::GrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel,
                    grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.get());
      }
      OS_ASSERT(result);
      return result;
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() {
      bool result = setString(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::GrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel, "autosize");
      OS_ASSERT(result);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setRatedAirFlowRateAtSelectedNominalSpeedLevel(
      boost::optional<double> ratedAirFlowRateAtSelectedNominalSpeedLevel) {
      bool result(false);
      if (ratedAirFlowRateAtSelectedNominalSpeedLevel) {
        result = setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedAirFlowRateAtSelectedNominalSpeedLevel,
                           ratedAirFlowRateAtSelectedNominalSpeedLevel.get());
      }
      OS_ASSERT(result);
      return result;
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel() {
      bool result =
        setString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedAirFlowRateAtSelectedNominalSpeedLevel, "autosize");
      OS_ASSERT(result);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setRatedWaterFlowRateAtSelectedNominalSpeedLevel(
      boost::optional<double> ratedWaterFlowRateAtSelectedNominalSpeedLevel) {
      bool result(false);
      if (ratedWaterFlowRateAtSelectedNominalSpeedLevel) {
        result = setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedWaterFlowRateAtSelectedNominalSpeedLevel,
                           ratedWaterFlowRateAtSelectedNominalSpeedLevel.get());
      }
      OS_ASSERT(result);
      return result;
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel() {
      bool result =
        setString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::RatedWaterFlowRateAtSelectedNominalSpeedLevel, "autosize");
      OS_ASSERT(result);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setNominalTimeforCondensatetoBeginLeavingtheCoil(
      double nominalTimeforCondensatetoBeginLeavingtheCoil) {
      bool result = setDouble(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::NominalTimeforCondensatetoBeginLeavingtheCoil,
                              nominalTimeforCondensatetoBeginLeavingtheCoil);
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(
      double initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity) {
      bool result = setDouble(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::InitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity,
        initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity);
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setUseHotGasReheat(bool useHotGasReheat) {
      return setBooleanFieldValue(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::UseHotGasReheat, useHotGasReheat);
      ;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setEnergyPartLoadFractionCurve(const Curve& curve) {
      bool result = setPointer(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::EnergyPartLoadFractionCurveName, curve.handle());
      return result;
    }

    boost::optional<Curve> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::optionalEnergyPartLoadFractionCurve() const {
      return getObject<ModelObject>().getModelObjectTarget<Curve>(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::EnergyPartLoadFractionCurveName);
    }

    ModelObject CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::clone(Model model) const {
      auto newCoil = WaterToAirComponent_Impl::clone(model).cast<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit>();

      if (auto speedDataList = this->speedDataList()) {
        auto speedDataListClone = speedDataList->clone(model).cast<ModelObjectList>();
        newCoil.getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setSpeedDataList(speedDataListClone);
      }

      return std::move(newCoil);
    }

    std::vector<ModelObject> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::children() const {
      std::vector<ModelObject> children;

      if (auto const _stageDataList = speedDataList()) {
        for (const auto& mo : _stageDataList->modelObjects()) {
          children.push_back(mo);
        }
      }

      children.push_back(energyPartLoadFractionCurve());

      std::vector<AirflowNetworkEquivalentDuct> myAFNItems =
        getObject<ModelObject>().getModelObjectSources<AirflowNetworkEquivalentDuct>(AirflowNetworkEquivalentDuct::iddObjectType());
      children.insert(children.end(), myAFNItems.begin(), myAFNItems.end());

      return children;
    }

    std::vector<openstudio::IdfObject> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::remove() {
      if (isRemovable()) {
        if (auto _stageDataList = speedDataList()) {
          _stageDataList->remove();
        }
        return WaterToAirComponent_Impl::remove();
      }

      return {};
    }

    boost::optional<HVACComponent> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::containingHVACComponent() const {
      // AirLoopHVACUnitarySystem
      auto const airLoopHVACUnitarySystems = this->model().getConcreteModelObjects<AirLoopHVACUnitarySystem>();

      for (const auto& airLoopHVACUnitarySystem : airLoopHVACUnitarySystems) {
        if (boost::optional<HVACComponent> coolingCoil = airLoopHVACUnitarySystem.coolingCoil()) {
          if (coolingCoil->handle() == this->handle()) {
            return airLoopHVACUnitarySystem;
          }
        }
      }
      return boost::none;
    }

    boost::optional<ZoneHVACComponent> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::containingZoneHVACComponent() const {
      // ZoneHVACWaterToAirHeatPump
      auto const zoneHVACWaterToAirHeatPumps = this->model().getConcreteModelObjects<ZoneHVACWaterToAirHeatPump>();

      for (const auto& zoneHVACWaterToAirHeatPump : zoneHVACWaterToAirHeatPumps) {
        if (boost::optional<HVACComponent> coil = zoneHVACWaterToAirHeatPump.coolingCoil()) {
          if (coil->handle() == this->handle()) {
            return zoneHVACWaterToAirHeatPump;
          }
        }
      }

      return boost::none;
    }

    boost::optional<ModelObjectList> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::speedDataList() const {
      return getObject<ModelObject>().getModelObjectTarget<ModelObjectList>(
        OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::SpeedDataList);
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::addSpeed(
      const CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData& speed) {
      auto modelObjectList = speedDataList();
      if (modelObjectList) {
        return modelObjectList->addModelObject(speed);
      }
      return false;
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::removeSpeed(
      const CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData& speed) {
      auto modelObjectList = speedDataList();
      if (modelObjectList) {
        modelObjectList->removeModelObject(speed);
      }
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::removeAllSpeeds() {
      auto modelObjectList = speedDataList();
      if (modelObjectList) {
        auto const modelObjects = modelObjectList->modelObjects();

        for (const auto& elem : modelObjects) {
          auto const modelObject = elem.optionalCast<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData>();
          if (modelObject) {
            modelObjectList->removeModelObject(elem);
          }
        }
      }
    }

    std::vector<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData>
      CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::speeds() const {
      std::vector<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData> result;
      auto const modelObjectList = speedDataList();
      if (modelObjectList) {
        auto const modelObjects = modelObjectList->modelObjects();

        for (const auto& elem : modelObjects) {
          auto const modelObject = elem.optionalCast<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData>();
          if (modelObject) {
            result.push_back(modelObject.get());
          }
        }
      }
      return result;
    }

    bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::setSpeedDataList(const boost::optional<ModelObjectList>& modelObjectList) {
      bool result(false);
      if (modelObjectList) {
        result = setPointer(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::SpeedDataList, modelObjectList.get().handle());
      } else {
        resetSpeedDataList();
        result = true;
      }
      return result;
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::resetSpeedDataList() {
      bool result = setString(OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFitFields::SpeedDataList, "");
      OS_ASSERT(result);
    }

    AirflowNetworkEquivalentDuct CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::getAirflowNetworkEquivalentDuct(double length,
                                                                                                                             double diameter) {
      boost::optional<AirflowNetworkEquivalentDuct> opt = airflowNetworkEquivalentDuct();
      if (opt) {
        if (opt->airPathLength() != length) {
          opt->setAirPathLength(length);
        }
        if (opt->airPathHydraulicDiameter() != diameter) {
          opt->setAirPathHydraulicDiameter(diameter);
        }
      }
      return AirflowNetworkEquivalentDuct(model(), length, diameter, handle());
    }

    boost::optional<AirflowNetworkEquivalentDuct> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::airflowNetworkEquivalentDuct() const {
      std::vector<AirflowNetworkEquivalentDuct> myAFN =
        getObject<ModelObject>().getModelObjectSources<AirflowNetworkEquivalentDuct>(AirflowNetworkEquivalentDuct::iddObjectType());
      auto count = myAFN.size();
      if (count == 1) {
        return myAFN[0];
      } else if (count > 1) {
        LOG(Warn, briefDescription() << " has more than one AirflowNetwork EquivalentDuct attached, returning first.");
        return myAFN[0];
      }
      return boost::none;
    }

    boost::optional<double>
      CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() const {
      // EPLUS-SQL-INCONSISTENCY
      return getAutosizedValue("Design Size Rated Total Cooling Capacity", "W", "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT");
    }

    boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel() const {
      // EPLUS-SQL-INCONSISTENCY
      return getAutosizedValue("Design Size Rated Air Flow Rate", "m3/s", "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT");
    }

    boost::optional<double>
      CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosizedRatedWaterFlowRateAtSelectedNominalSpeedLevel() const {
      // EPLUS-SQL-INCONSISTENCY
      return getAutosizedValue("Design Size Rated Air Flow Rate", "m3/s", "COIL:COOLING:WATERTOAIRHEATPUMP:VARIABLESPEEDEQUATIONFIT");
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::autosize() {
      autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
      autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel();
      autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel();
    }

    void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::applySizingValues() {
      boost::optional<double> val;
      val = autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
      if (val) {
        setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(val.get());
      }

      val = autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel();
      if (val) {
        setRatedAirFlowRateAtSelectedNominalSpeedLevel(val.get());
      }

      val = autosizedRatedWaterFlowRateAtSelectedNominalSpeedLevel();
      if (val) {
        setRatedWaterFlowRateAtSelectedNominalSpeedLevel(val.get());
      }
    }

    ComponentType CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::componentType() const {
      return ComponentType::Cooling;
    }

    std::vector<FuelType> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::coolingFuelTypes() const {
      std::set<FuelType> result;
      result.insert(FuelType::Electricity);
      if (auto p_ = plantLoop()) {
        for (auto ft : p_->coolingFuelTypes()) {
          result.insert(ft);
        }
      }
      return {result.begin(), result.end()};
    }

    std::vector<FuelType> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::heatingFuelTypes() const {
      return {};
    }

    std::vector<AppGFuelType> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl::appGHeatingFuelTypes() const {
      return {};
    }

  }  // namespace detail

  CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit(const Model& model)
    : WaterToAirComponent(CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType(), model) {
    OS_ASSERT(getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>());

    auto always_on = model.alwaysOnDiscreteSchedule();
    bool ok = setAvailabilitySchedule(always_on);
    OS_ASSERT(ok);
    ok = setNominalSpeedLevel(1);
    OS_ASSERT(ok);
    autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
    autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel();
    autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel();
    ok = setNominalTimeforCondensatetoBeginLeavingtheCoil(0);
    OS_ASSERT(ok);
    ok = setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(0);
    OS_ASSERT(ok);
    // E+ 23.2.0 defaults Maximum Cycling Rate and Latent Capacity Time Constant to 0.0, we don't, cf #4999
    ok = setMaximumCyclingRate(2.5);
    OS_ASSERT(ok);
    ok = setLatentCapacityTimeConstant(60.0);
    OS_ASSERT(ok);
    ok = setFanDelayTime(60.0);
    OS_ASSERT(ok);
    setUseHotGasReheat(false);

    // Note: this predates v23.2.0. Consider switching to CurveLinear::defaultHeatPumpCoilPLFCorrelationCurve (would calculate c1=0.8337, c2=0.1662)
    auto partLoadFraction = CurveQuadratic(model);
    partLoadFraction.setCoefficient1Constant(0.85);
    partLoadFraction.setCoefficient2x(0.15);
    partLoadFraction.setCoefficient3xPOW2(0.0);
    partLoadFraction.setMinimumValueofx(0.0);
    partLoadFraction.setMaximumValueofx(1.0);

    ok = setEnergyPartLoadFractionCurve(partLoadFraction);
    OS_ASSERT(ok);

    auto speedDataList = ModelObjectList(model);
    speedDataList.setName(this->name().get() + " Speed Data List");
    ok = getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setSpeedDataList(speedDataList);
    OS_ASSERT(ok);
  }

  CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit(const Model& model,
                                                                                                               const Curve& partLoadFraction)
    : WaterToAirComponent(CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType(), model) {
    OS_ASSERT(getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>());

    auto always_on = model.alwaysOnDiscreteSchedule();
    bool ok = setAvailabilitySchedule(always_on);
    OS_ASSERT(ok);
    ok = setNominalSpeedLevel(1);
    OS_ASSERT(ok);
    autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
    autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel();
    autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel();
    ok = setNominalTimeforCondensatetoBeginLeavingtheCoil(0);
    OS_ASSERT(ok);
    ok = setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(0);
    OS_ASSERT(ok);
    // E+ 23.2.0 defaults Maximum Cycling Rate and Latent Capacity Time Constant to 0.0, we don't, cf #4999
    ok = setMaximumCyclingRate(2.5);
    OS_ASSERT(ok);
    ok = setLatentCapacityTimeConstant(60.0);
    OS_ASSERT(ok);
    ok = setFanDelayTime(60.0);
    OS_ASSERT(ok);
    setUseHotGasReheat(false);
    ok = setEnergyPartLoadFractionCurve(partLoadFraction);
    OS_ASSERT(ok);

    auto speedDataList = ModelObjectList(model);
    speedDataList.setName(this->name().get() + " Speed Data List");
    ok = getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setSpeedDataList(speedDataList);
    OS_ASSERT(ok);
  }

  IddObjectType CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::iddObjectType() {
    return {IddObjectType::OS_Coil_Cooling_WaterToAirHeatPump_VariableSpeedEquationFit};
  }

  Schedule CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::availabilitySchedule() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->availabilitySchedule();
  }

  int CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::nominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->nominalSpeedLevel();
  }

  boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::isGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevelAutosized() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->isGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevelAutosized();
  }

  boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::ratedAirFlowRateAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->ratedAirFlowRateAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::isRatedAirFlowRateAtSelectedNominalSpeedLevelAutosized() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->isRatedAirFlowRateAtSelectedNominalSpeedLevelAutosized();
  }

  boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::ratedWaterFlowRateAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->ratedWaterFlowRateAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::isRatedWaterFlowRateAtSelectedNominalSpeedLevelAutosized() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->isRatedWaterFlowRateAtSelectedNominalSpeedLevelAutosized();
  }

  double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::nominalTimeforCondensatetoBeginLeavingtheCoil() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->nominalTimeforCondensatetoBeginLeavingtheCoil();
  }

  double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::useHotGasReheat() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->useHotGasReheat();
  }

  Curve CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::energyPartLoadFractionCurve() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->energyPartLoadFractionCurve();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setAvailabilitySchedule(Schedule& schedule) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setAvailabilitySchedule(schedule);
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setNominalSpeedLevel(int nominalSpeedLevel) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setNominalSpeedLevel(nominalSpeedLevel);
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(
    double grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel);
  }

  void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() {
    getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->autosizeGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setRatedAirFlowRateAtSelectedNominalSpeedLevel(
    double ratedAirFlowRateAtSelectedNominalSpeedLevel) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setRatedAirFlowRateAtSelectedNominalSpeedLevel(
      ratedAirFlowRateAtSelectedNominalSpeedLevel);
  }

  void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel() {
    getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->autosizeRatedAirFlowRateAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setRatedWaterFlowRateAtSelectedNominalSpeedLevel(
    double ratedWaterFlowRateAtSelectedNominalSpeedLevel) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setRatedWaterFlowRateAtSelectedNominalSpeedLevel(
      ratedWaterFlowRateAtSelectedNominalSpeedLevel);
  }

  void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel() {
    getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->autosizeRatedWaterFlowRateAtSelectedNominalSpeedLevel();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setNominalTimeforCondensatetoBeginLeavingtheCoil(
    double nominalTimeforCondensatetoBeginLeavingtheCoil) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setNominalTimeforCondensatetoBeginLeavingtheCoil(
      nominalTimeforCondensatetoBeginLeavingtheCoil);
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(
    double initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->setInitialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity(initialMoistureEvaporationRateDividedbySteadyStateACLatentCapacity);
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setUseHotGasReheat(bool useHotGasReheat) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setUseHotGasReheat(useHotGasReheat);
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setEnergyPartLoadFractionCurve(const Curve& curve) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setEnergyPartLoadFractionCurve(curve);
  }

  std::vector<CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::speeds() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->speeds();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::addSpeed(const CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData& speed) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->addSpeed(speed);
  }

  void
    CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::removeSpeed(const CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFitSpeedData& speed) {
    getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->removeSpeed(speed);
  }

  void CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::removeAllSpeeds() {
    getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->removeAllSpeeds();
  }

  double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::maximumCyclingRate() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->maximumCyclingRate();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setMaximumCyclingRate(double maximumCyclingRate) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setMaximumCyclingRate(maximumCyclingRate);
  }

  double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::latentCapacityTimeConstant() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->latentCapacityTimeConstant();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setLatentCapacityTimeConstant(double latentCapacityTimeConstant) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setLatentCapacityTimeConstant(latentCapacityTimeConstant);
  }

  double CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::fanDelayTime() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->fanDelayTime();
  }

  bool CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::setFanDelayTime(double fanDelayTime) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->setFanDelayTime(fanDelayTime);
  }

  /// @cond
  CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit(
    std::shared_ptr<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl> impl)
    : WaterToAirComponent(std::move(impl)) {}
  /// @endcond

  AirflowNetworkEquivalentDuct CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::getAirflowNetworkEquivalentDuct(double length,
                                                                                                                      double diameter) {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->getAirflowNetworkEquivalentDuct(length, diameter);
  }

  boost::optional<AirflowNetworkEquivalentDuct> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::airflowNetworkEquivalentDuct() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->airflowNetworkEquivalentDuct();
  }

  boost::optional<double>
    CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()
      ->autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel();
  }

  boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel();
  }

  boost::optional<double> CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit::autosizedRatedWaterFlowRateAtSelectedNominalSpeedLevel() const {
    return getImpl<detail::CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit_Impl>()->autosizedRatedWaterFlowRateAtSelectedNominalSpeedLevel();
  }

}  // namespace model
}  // namespace openstudio
